package storage

import (
	"github.com/tokentransfer/node/core"
	"github.com/tokentransfer/node/util"
)

type ProtoChunkBinary struct {
	t int64
}

func (cb *ProtoChunkBinary) getType() int64 {
	return cb.t
}

func (cb *ProtoChunkBinary) marshalEntry(e *chunkEntry) ([]byte, error) {
	ll := len(e.chunks)
	chunks := make([]interface{}, ll)
	for i := 0; i < ll; i++ {
		ck := e.chunks[i]
		chunks[i] = map[string]interface{}{
			"key":     []byte(ck.key[:]),
			"nextPos": int64(ck.nextPos),
		}
	}
	data, err := core.MarshalData(map[string]interface{}{
		"name":   e.name,
		"data":   e.data,
		"chunks": chunks,
		"refs":   int64(e.refs),
	})
	if err != nil {
		return nil, err
	}
	return data, nil
}

func (cb *ProtoChunkBinary) unmarshalEntry(e *chunkEntry, data []byte) error {
	dt, o, err := core.UnmarshalData(data)
	if err != nil {
		return err
	}
	if dt != core.CORE_DATA_MAP {
		return util.ErrorOfInvalid("data map", "entry")
	}
	em := o.(map[string]interface{})

	e.name = util.ToString(&em, "name")
	e.data = util.ToBytes(&em, "data")

	list := util.ToArray(&em, "chunks")
	if list != nil {
		ll := len(list)
		chunks := make([]chunkOffset, ll)
		for i := 0; i < ll; i++ {
			c := chunkOffset{}
			cm := list[i].(map[string]interface{})
			c.key = core.Key(util.ToBytes(&cm, "key"))
			c.nextPos = util.ToInt64(&cm, "nextPos")
			chunks[i] = c
		}
		e.chunks = chunks
	}
	e.refs = int(util.ToInt64(&em, "refs"))
	return nil
}

func (cb *ProtoChunkBinary) marshalItem(e *chunkItem) ([]byte, error) {
	data, err := core.MarshalData(map[string]interface{}{
		"name":  e.name,
		"key":   []byte(e.key[:]),
		"group": e.group,
	})
	if err != nil {
		return nil, err
	}
	return data, nil
}

func (cb *ProtoChunkBinary) unmarshalItem(e *chunkItem, data []byte) error {
	dt, o, err := core.UnmarshalData(data)
	if err != nil {
		return err
	}
	if dt != core.CORE_DATA_MAP {
		return util.ErrorOfInvalid("data map", "item")
	}
	im := o.(map[string]interface{})

	e.name = util.ToString(&im, "name")
	e.key = core.Key(util.ToBytes(&im, "key"))
	e.group = util.ToBoolean(&im, "group")
	return nil
}
